home *** CD-ROM | disk | FTP | other *** search
- /****************************************************************************
- * quadrics.c
- *
- * This module implements the code for the quadric shape primitive.
- *
- * from Persistence of Vision(tm) Ray Tracer
- * Copyright 1996 Persistence of Vision Team
- *---------------------------------------------------------------------------
- * NOTICE: This source code file is provided so that users may experiment
- * with enhancements to POV-Ray and to port the software to platforms other
- * than those supported by the POV-Ray Team. There are strict rules under
- * which you are permitted to use this file. The rules are in the file
- * named POVLEGAL.DOC which should be distributed with this file. If
- * POVLEGAL.DOC is not available or for more info please contact the POV-Ray
- * Team Coordinator by leaving a message in CompuServe's Graphics Developer's
- * Forum. The latest version of POV-Ray may be found there as well.
- *
- * This program is based on the popular DKB raytracer version 2.12.
- * DKBTrace was originally written by David K. Buck.
- * DKBTrace Ver 2.0-2.12 were written by David K. Buck & Aaron A. Collins.
- *
- *****************************************************************************/
-
- #include "frame.h"
- #include "povray.h"
- #include "vector.h"
- #include "povproto.h"
- #include "bbox.h"
- #include "objects.h"
- #include "matrices.h"
- #include "planes.h"
- #include "quadrics.h"
-
-
-
- /*****************************************************************************
- * Local preprocessor defines
- ******************************************************************************/
-
- /* The following defines make typing much easier! [DB 7/94] */
-
- #define Xd Ray->Direction[X]
- #define Yd Ray->Direction[Y]
- #define Zd Ray->Direction[Z]
-
- #define Xo Ray->Initial[X]
- #define Yo Ray->Initial[Y]
- #define Zo Ray->Initial[Z]
-
- #define QA Quadric->Square_Terms[X]
- #define QE Quadric->Square_Terms[Y]
- #define QH Quadric->Square_Terms[Z]
-
- #define QB Quadric->Mixed_Terms[X]
- #define QC Quadric->Mixed_Terms[Y]
- #define QF Quadric->Mixed_Terms[Z]
-
- #define QD Quadric->Terms[X]
- #define QG Quadric->Terms[Y]
- #define QI Quadric->Terms[Z]
-
- #define QJ Quadric->Constant
-
-
-
- /*****************************************************************************
- * Static functions
- ******************************************************************************/
-
- static int Intersect_Quadric PARAMS((RAY *Ray, QUADRIC *Quadric, DBL *Depth1, DBL *Depth2));
- static void Quadric_To_Matrix PARAMS((QUADRIC *Quadric, MATRIX Matrix));
- static void Matrix_To_Quadric PARAMS((MATRIX Matrix, QUADRIC *Quadric));
- static int All_Quadric_Intersections PARAMS((OBJECT *Object, RAY *Ray, ISTACK *Depth_Stack));
- static int Inside_Quadric PARAMS((VECTOR IPoint, OBJECT *Object));
- static void Quadric_Normal PARAMS((VECTOR Result, OBJECT *Object, INTERSECTION *Inter));
- static void *Copy_Quadric PARAMS((OBJECT *Object));
- static void Translate_Quadric PARAMS((OBJECT *Object, VECTOR Vector, TRANSFORM *Trans));
- static void Rotate_Quadric PARAMS((OBJECT *Object, VECTOR Vector, TRANSFORM *Trans));
- static void Scale_Quadric PARAMS((OBJECT *Object, VECTOR Vector, TRANSFORM *Trans));
- static void Transform_Quadric PARAMS((OBJECT *Object, TRANSFORM *Trans));
- static void Invert_Quadric PARAMS((OBJECT *Object));
- static void Destroy_Quadric PARAMS((OBJECT *Object));
-
- /*****************************************************************************
- * Local variables
- ******************************************************************************/
-
- METHODS Quadric_Methods =
- {
- All_Quadric_Intersections,
- Inside_Quadric, Quadric_Normal,
- Copy_Quadric,
- Translate_Quadric, Rotate_Quadric,
- Scale_Quadric, Transform_Quadric, Invert_Quadric,
- Destroy_Quadric
- };
-
-
-
-
- /*****************************************************************************
- *
- * FUNCTION
- *
- * All_Quadric_Intersections
- *
- * INPUT
- *
- * OUTPUT
- *
- * RETURNS
- *
- * AUTHOR
- *
- * POV-Ray Team
- *
- * DESCRIPTION
- *
- * -
- *
- * CHANGES
- *
- * -
- *
- ******************************************************************************/
-
- static int All_Quadric_Intersections(Object, Ray, Depth_Stack)
- OBJECT *Object;
- RAY *Ray;
- ISTACK *Depth_Stack;
- {
- DBL Depth1, Depth2;
- VECTOR IPoint;
- register int Intersection_Found;
-
- Intersection_Found = FALSE;
-
- if (Intersect_Quadric(Ray, (QUADRIC *)Object, &Depth1, &Depth2))
- {
- if ((Depth1 > Small_Tolerance) && (Depth1 < Max_Distance))
- {
- VEvaluateRay(IPoint, Ray->Initial, Depth1, Ray->Direction);
-
- if (Point_In_Clip(IPoint, Object->Clip))
- {
- push_entry(Depth1, IPoint, Object, Depth_Stack);
-
- Intersection_Found = TRUE;
- }
- }
-
- if ((Depth2 > Small_Tolerance) && (Depth2 < Max_Distance))
- {
- VEvaluateRay(IPoint, Ray->Initial, Depth2, Ray->Direction);
-
- if (Point_In_Clip(IPoint, Object->Clip))
- {
- push_entry(Depth2, IPoint, Object, Depth_Stack);
-
- Intersection_Found = TRUE;
- }
- }
- }
-
- return(Intersection_Found);
- }
-
-
-
- /*****************************************************************************
- *
- * FUNCTION
- *
- * Intersect_Quadric
- *
- * INPUT
- *
- * OUTPUT
- *
- * RETURNS
- *
- * AUTHOR
- *
- * POV-Ray Team
- *
- * DESCRIPTION
- *
- * -
- *
- * CHANGES
- *
- * -
- *
- ******************************************************************************/
-
- static int Intersect_Quadric(Ray, Quadric, Depth1, Depth2)
- RAY *Ray;
- QUADRIC *Quadric;
- DBL *Depth1, *Depth2;
- {
- register DBL a, b, c, d;
-
- Increase_Counter(stats[Ray_Quadric_Tests]);
-
- a = Xd * (QA * Xd + QB * Yd + QC * Zd) +
- Yd * (QE * Yd + QF * Zd) +
- QH * Zd * Zd;
-
- b = Xd * (QA * Xo + 0.5 * (QB * Yo + QC * Zo + QD)) +
- Yd * (QE * Yo + 0.5 * (QB * Xo + QF * Zo + QG)) +
- Zd * (QH * Zo + 0.5 * (QC * Xo + QF * Yo + QI));
-
- c = Xo * (QA * Xo + QB * Yo + QC * Zo + QD) +
- Yo * (QE * Yo + QF * Zo + QG) +
- Zo * (QH * Zo + QI) +
- QJ;
-
- if (a != 0.0)
- {
- /* The equation is quadratic - find its roots */
-
- d = Sqr(b) - a * c;
-
- if (d <= 0.0)
- {
- return(FALSE);
- }
-
- d = sqrt (d);
-
- *Depth1 = (-b + d) / (a);
- *Depth2 = (-b - d) / (a);
- }
- else
- {
- /* There are no quadratic terms. Solve the linear equation instead. */
-
- if (b == 0.0)
- {
- return(FALSE);
- }
-
- *Depth1 = - 0.5 * c / b;
- *Depth2 = Max_Distance;
- }
-
- Increase_Counter(stats[Ray_Quadric_Tests_Succeeded]);
-
- return(TRUE);
- }
-
-
-
- /*****************************************************************************
- *
- * FUNCTION
- *
- * Inside_Quadric
- *
- * INPUT
- *
- * OUTPUT
- *
- * RETURNS
- *
- * AUTHOR
- *
- * POV-Ray Team
- *
- * DESCRIPTION
- *
- * -
- *
- * CHANGES
- *
- * -
- *
- ******************************************************************************/
-
- static int Inside_Quadric(IPoint, Object)
- VECTOR IPoint;
- OBJECT *Object;
- {
- QUADRIC *Quadric = (QUADRIC *)Object;
-
- /* This is faster and shorter. [DB 7/94] */
-
- return((IPoint[X] * (QA * IPoint[X] + QB * IPoint[Y] + QD) +
- IPoint[Y] * (QE * IPoint[Y] + QF * IPoint[Z] + QG) +
- IPoint[Z] * (QH * IPoint[Z] + QC * IPoint[X] + QI) + QJ) <= 0.0);
- }
-
-
-
- /*****************************************************************************
- *
- * FUNCTION
- *
- * Quadric_Normal
- *
- * INPUT
- *
- * OUTPUT
- *
- * RETURNS
- *
- * AUTHOR
- *
- * POV-Ray Team
- *
- * DESCRIPTION
- *
- * -
- *
- * CHANGES
- *
- * -
- *
- ******************************************************************************/
-
- static void Quadric_Normal(Result, Object, Inter)
- OBJECT *Object;
- VECTOR Result;
- INTERSECTION *Inter;
- {
- QUADRIC *Quadric = (QUADRIC *) Object;
- DBL Len;
-
- /* This is faster and shorter. [DB 7/94] */
-
- Result[X] = 2.0 * QA * Inter->IPoint[X] +
- QB * Inter->IPoint[Y] +
- QC * Inter->IPoint[Z] +
- QD;
-
- Result[Y] = QB * Inter->IPoint[X] +
- 2.0 * QE * Inter->IPoint[Y] +
- QF * Inter->IPoint[Z] +
- QG;
-
- Result[Z] = QC * Inter->IPoint[X] +
- QF * Inter->IPoint[Y] +
- 2.0 * QH * Inter->IPoint[Z] +
- QI;
-
- VLength(Len, Result);
-
- if (Len == 0.0)
- {
- /* The normal is not defined at this point of the surface. */
- /* Set it to any arbitrary direction. */
-
- Make_Vector(Result, 1.0, 0.0, 0.0);
- }
- else
- {
- VInverseScaleEq(Result, Len);
- }
- }
-
-
-
- /*****************************************************************************
- *
- * FUNCTION
- *
- * Transform_Quadric
- *
- * INPUT
- *
- * OUTPUT
- *
- * RETURNS
- *
- * AUTHOR
- *
- * POV-Ray Team
- *
- * DESCRIPTION
- *
- * -
- *
- * CHANGES
- *
- * -
- *
- ******************************************************************************/
-
- static void Transform_Quadric(Object, Trans)
- OBJECT *Object;
- TRANSFORM *Trans;
- {
- QUADRIC *Quadric=(QUADRIC *)Object;
- MATRIX Quadric_Matrix, Transform_Transposed;
-
- Quadric_To_Matrix (Quadric, Quadric_Matrix);
-
- MTimes (Quadric_Matrix, Trans->inverse, Quadric_Matrix);
- MTranspose (Transform_Transposed, Trans->inverse);
- MTimes (Quadric_Matrix, Quadric_Matrix, Transform_Transposed);
-
- Matrix_To_Quadric (Quadric_Matrix, Quadric);
-
- Recompute_BBox(&Object->BBox, Trans);
- }
-
-
-
- /*****************************************************************************
- *
- * FUNCTION
- *
- * Quadric_To_Matrix
- *
- * INPUT
- *
- * OUTPUT
- *
- * RETURNS
- *
- * AUTHOR
- *
- * POV-Ray Team
- *
- * DESCRIPTION
- *
- * -
- *
- * CHANGES
- *
- * -
- *
- ******************************************************************************/
-
- static void Quadric_To_Matrix(Quadric, Matrix)
- QUADRIC *Quadric;
- MATRIX Matrix;
- {
- MZero (Matrix);
-
- Matrix[0][0] = Quadric->Square_Terms[X];
- Matrix[1][1] = Quadric->Square_Terms[Y];
- Matrix[2][2] = Quadric->Square_Terms[Z];
- Matrix[0][1] = Quadric->Mixed_Terms[X];
- Matrix[0][2] = Quadric->Mixed_Terms[Y];
- Matrix[0][3] = Quadric->Terms[X];
- Matrix[1][2] = Quadric->Mixed_Terms[Z];
- Matrix[1][3] = Quadric->Terms[Y];
- Matrix[2][3] = Quadric->Terms[Z];
- Matrix[3][3] = Quadric->Constant;
- }
-
-
-
- /*****************************************************************************
- *
- * FUNCTION
- *
- * Matrix_To_Quadric
- *
- * INPUT
- *
- * OUTPUT
- *
- * RETURNS
- *
- * AUTHOR
- *
- * POV-Ray Team
- *
- * DESCRIPTION
- *
- * -
- *
- * CHANGES
- *
- * -
- *
- ******************************************************************************/
-
- static void Matrix_To_Quadric(Matrix, Quadric)
- MATRIX Matrix;
- QUADRIC *Quadric;
- {
- Quadric->Square_Terms[X] = Matrix[0][0];
- Quadric->Square_Terms[Y] = Matrix[1][1];
- Quadric->Square_Terms[Z] = Matrix[2][2];
-
- Quadric->Mixed_Terms[X] = Matrix[0][1] + Matrix[1][0];
- Quadric->Mixed_Terms[Y] = Matrix[0][2] + Matrix[2][0];
- Quadric->Mixed_Terms[Z] = Matrix[1][2] + Matrix[2][1];
-
- Quadric->Terms[X] = Matrix[0][3] + Matrix[3][0];
- Quadric->Terms[Y] = Matrix[1][3] + Matrix[3][1];
- Quadric->Terms[Z] = Matrix[2][3] + Matrix[3][2];
-
- Quadric->Constant = Matrix[3][3];
- }
-
-
-
- /*****************************************************************************
- *
- * FUNCTION
- *
- * Translate_Quadric
- *
- * INPUT
- *
- * OUTPUT
- *
- * RETURNS
- *
- * AUTHOR
- *
- * POV-Ray Team
- *
- * DESCRIPTION
- *
- * -
- *
- * CHANGES
- *
- * -
- *
- ******************************************************************************/
-
- static void Translate_Quadric(Object, Vector, Trans)
- OBJECT *Object;
- VECTOR Vector;
- TRANSFORM *Trans;
- {
- Transform_Quadric (Object, Trans);
- }
-
-
-
- /*****************************************************************************
- *
- * FUNCTION
- *
- * Rotate_Quadric
- *
- * INPUT
- *
- * OUTPUT
- *
- * RETURNS
- *
- * AUTHOR
- *
- * POV-Ray Team
- *
- * DESCRIPTION
- *
- * -
- *
- * CHANGES
- *
- * -
- *
- ******************************************************************************/
-
- static void Rotate_Quadric(Object, Vector, Trans)
- OBJECT *Object;
- VECTOR Vector;
- TRANSFORM *Trans;
- {
- Transform_Quadric (Object, Trans);
- }
-
-
-
- /*****************************************************************************
- *
- * FUNCTION
- *
- * Scale_Quadric
- *
- * INPUT
- *
- * OUTPUT
- *
- * RETURNS
- *
- * AUTHOR
- *
- * POV-Ray Team
- *
- * DESCRIPTION
- *
- * -
- *
- * CHANGES
- *
- * -
- *
- ******************************************************************************/
-
- static void Scale_Quadric(Object, Vector, Trans)
- OBJECT *Object;
- VECTOR Vector;
- TRANSFORM *Trans;
- {
- Transform_Quadric (Object, Trans);
- }
-
-
-
- /*****************************************************************************
- *
- * FUNCTION
- *
- * Invert_Quadric
- *
- * INPUT
- *
- * OUTPUT
- *
- * RETURNS
- *
- * AUTHOR
- *
- * POV-Ray Team
- *
- * DESCRIPTION
- *
- * -
- *
- * CHANGES
- *
- * -
- *
- ******************************************************************************/
-
- static void Invert_Quadric(Object)
- OBJECT *Object;
- {
- QUADRIC *Quadric = (QUADRIC *) Object;
-
- VScaleEq(Quadric->Square_Terms, -1.0);
- VScaleEq(Quadric->Mixed_Terms, -1.0);
- VScaleEq(Quadric->Terms, -1.0);
-
- Quadric->Constant *= -1.0;
-
- Invert_Flag(Object, INVERTED_FLAG);
- }
-
-
-
- /*****************************************************************************
- *
- * FUNCTION
- *
- * Create_Quadric
- *
- * INPUT
- *
- * OUTPUT
- *
- * RETURNS
- *
- * AUTHOR
- *
- * POV-Ray Team
- *
- * DESCRIPTION
- *
- * -
- *
- * CHANGES
- *
- * -
- *
- ******************************************************************************/
-
- QUADRIC *Create_Quadric()
- {
- QUADRIC *New;
-
- New = (QUADRIC *)POV_MALLOC(sizeof (QUADRIC), "quadric");
-
- INIT_OBJECT_FIELDS(New, QUADRIC_OBJECT, &Quadric_Methods)
-
- Make_Vector (New->Square_Terms, 1.0, 1.0, 1.0);
- Make_Vector (New->Mixed_Terms, 0.0, 0.0, 0.0);
- Make_Vector (New->Terms, 0.0, 0.0, 0.0);
- New->Constant = 1.0;
-
- return(New);
- }
-
-
-
- /*****************************************************************************
- *
- * FUNCTION
- *
- * Copy_Quadric
- *
- * INPUT
- *
- * OUTPUT
- *
- * RETURNS
- *
- * AUTHOR
- *
- * POV-Ray Team
- *
- * DESCRIPTION
- *
- * -
- *
- * CHANGES
- *
- * -
- *
- ******************************************************************************/
-
- static void *Copy_Quadric(Object)
- OBJECT *Object;
- {
- QUADRIC *New;
-
- New = Create_Quadric();
-
- *New = *((QUADRIC *)Object);
-
- return(New);
- }
-
-
-
- /*****************************************************************************
- *
- * FUNCTION
- *
- * Destroy_Quadric
- *
- * INPUT
- *
- * OUTPUT
- *
- * RETURNS
- *
- * AUTHOR
- *
- * POV-Ray Team
- *
- * DESCRIPTION
- *
- * -
- *
- * CHANGES
- *
- * -
- *
- ******************************************************************************/
-
- static void Destroy_Quadric(Object)
- OBJECT *Object;
- {
- POV_FREE (Object);
- }
-
-
-
- /*****************************************************************************
- *
- * FUNCTION
- *
- * Compute_Quadric_BBox
- *
- * INPUT
- *
- * Quadric - Qaudric object
- *
- * OUTPUT
- *
- * Quadric
- *
- * RETURNS
- *
- * AUTHOR
- *
- * Dieter Bayer
- *
- * DESCRIPTION
- *
- * Compute a bounding box around a quadric.
- *
- * This function calculates the bounding box of a quadric given in
- * its normal form, i.e. f(x,y,z) = A*x^2 + E*y^2 + H*z^2 + J = 0.
- *
- * NOTE: Translated quadrics can also be bounded by this function.
- *
- * Supported: cones, cylinders, ellipsoids, hyperboloids.
- *
- * CHANGES
- *
- * May 1994 : Creation.
- *
- * Sep 1994 : Added support of hyperpoloids. Improved bounding of
- * quadrics used in CSG intersections. [DB]
- *
- ******************************************************************************/
-
- void Compute_Quadric_BBox(Quadric, ClipMin, ClipMax)
- QUADRIC *Quadric;
- VECTOR ClipMin, ClipMax;
- {
- DBL A, B, C, D, E, F, G, H, I, J;
- DBL a, b, c, d;
- DBL rx, ry, rz, rx1, rx2, ry1, ry2, rz1, rz2, x, y, z;
- DBL New_Volume, Old_Volume;
- VECTOR Min, Max, TmpMin, TmpMax, NewMin, NewMax, T1;
- BBOX Old;
- OBJECT *Sib;
-
- /*
- * Check for 'normal' form. If the quadric isn't in it's normal form
- * we can't do anything (we could, but that would be to tedious!
- * Diagonalising the quadric's 4x4 matrix, i.e. finding its eigenvalues
- * and eigenvectors -> solving a 4th order polynom).
- */
-
- /* Get quadrics coefficients. */
-
- A = Quadric->Square_Terms[X];
- E = Quadric->Square_Terms[Y];
- H = Quadric->Square_Terms[Z];
- B = Quadric->Mixed_Terms[X] / 2.0;
- C = Quadric->Mixed_Terms[Y] / 2.0;
- F = Quadric->Mixed_Terms[Z] / 2.0;
- D = Quadric->Terms[X] / 2.0;
- G = Quadric->Terms[Y] / 2.0;
- I = Quadric->Terms[Z] / 2.0;
- J = Quadric->Constant;
-
- /* Set small values to 0. */
-
- if (fabs(A) < EPSILON) A = 0.0;
- if (fabs(B) < EPSILON) B = 0.0;
- if (fabs(C) < EPSILON) C = 0.0;
- if (fabs(D) < EPSILON) D = 0.0;
- if (fabs(E) < EPSILON) E = 0.0;
- if (fabs(F) < EPSILON) F = 0.0;
- if (fabs(G) < EPSILON) G = 0.0;
- if (fabs(H) < EPSILON) H = 0.0;
- if (fabs(I) < EPSILON) I = 0.0;
- if (fabs(J) < EPSILON) J = 0.0;
-
- /* Non-zero mixed terms --> return */
-
- if ((B != 0.0) || (C != 0.0) || (F != 0.0))
- {
- return;
- }
-
- /* Non-zero linear terms --> get translation vector */
-
- if ((D != 0.0) || (G != 0.0) || (I != 0.0))
- {
- if (A != 0.0)
- {
- T1[X] = -D / A;
- }
- else
- {
- if (D != 0.0)
- {
- T1[X] = J / (2.0 * D);
- }
- else
- {
- T1[X] = 0.0;
- }
- }
-
- if (E != 0.0)
- {
- T1[Y] = -G / E;
- }
- else
- {
- if (G != 0.0)
- {
- T1[Y] = J / (2.0 * G);
- }
- else
- {
- T1[Y] = 0.0;
- }
- }
-
- if (H != 0.0)
- {
- T1[Z] = -I / H;
- }
- else
- {
- if (I != 0.0)
- {
- T1[Z] = J / (2.0 * I);
- }
- else
- {
- T1[Z] = 0.0;
- }
- }
-
- /* Recalculate coefficients. */
-
- D += A * T1[X];
- G += E * T1[Y];
- I += H * T1[Z];
- J -= T1[X]*(A*T1[X] + 2.0*D) + T1[Y]*(E*T1[Y] + 2.0*G) + T1[Z]*(H*T1[Z] + 2.0*I);
- }
- else
- {
- Make_Vector(T1, 0.0, 0.0, 0.0);
- }
-
- /* Get old bounding box. */
-
- Old = Quadric->BBox;
-
- /* Init new bounding box. */
-
- NewMin[X] = NewMin[Y] = NewMin[Z] = -BOUND_HUGE/2;
- NewMax[X] = NewMax[Y] = NewMax[Z] = BOUND_HUGE/2;
-
- /* Get the bounding box of the clipping object. */
-
- if (Quadric->Clip != NULL)
- {
- Min[X] = Min[Y] = Min[Z] = -BOUND_HUGE;
- Max[X] = Max[Y] = Max[Z] = BOUND_HUGE;
-
- /* Intersect the members bounding boxes. */
-
- for (Sib = Quadric->Clip; Sib != NULL; Sib = Sib->Sibling)
- {
- if (!Test_Flag(Sib, INVERTED_FLAG))
- {
- if (Sib->Methods == &Plane_Methods)
- {
- Compute_Plane_Min_Max((PLANE *)Sib, TmpMin, TmpMax);
- }
- else
- {
- Make_min_max_from_BBox(TmpMin, TmpMax, Sib->BBox);
- }
-
- Min[X] = max(Min[X], TmpMin[X]);
- Min[Y] = max(Min[Y], TmpMin[Y]);
- Min[Z] = max(Min[Z], TmpMin[Z]);
- Max[X] = min(Max[X], TmpMax[X]);
- Max[Y] = min(Max[Y], TmpMax[Y]);
- Max[Z] = min(Max[Z], TmpMax[Z]);
- }
- }
-
- Assign_Vector(ClipMin, Min);
- Assign_Vector(ClipMax, Max);
- }
-
- /* Translate clipping box. */
-
- VSubEq(ClipMin, T1);
- VSubEq(ClipMax, T1);
-
- /* We want A to be non-negative. */
-
- if (A < 0.0)
- {
- A = -A;
- D = -D;
- E = -E;
- G = -G;
- H = -H;
- I = -I;
- J = -J;
- }
-
- /*
- *
- * Check for ellipsoid.
- *
- * x*x y*y z*z
- * ----- + ----- + ----- - 1 = 0
- * a*a b*b c*c
- *
- */
-
- if ((A > 0.0) && (E > 0.0) && (H > 0.0) && (J < 0.0))
- {
- a = sqrt(-J/A);
- b = sqrt(-J/E);
- c = sqrt(-J/H);
-
- NewMin[X] = -a;
- NewMin[Y] = -b;
- NewMin[Z] = -c;
- NewMax[X] = a;
- NewMax[Y] = b;
- NewMax[Z] = c;
- }
-
- /*
- *
- * Check for cylinder (x-axis).
- *
- * y*y z*z
- * ----- + ----- - 1 = 0
- * b*b c*c
- *
- */
-
- if ((A == 0.0) && (E > 0.0) && (H > 0.0) && (J < 0.0))
- {
- b = sqrt(-J/E);
- c = sqrt(-J/H);
-
- NewMin[Y] = -b;
- NewMin[Z] = -c;
- NewMax[Y] = b;
- NewMax[Z] = c;
- }
-
- /*
- *
- * Check for cylinder (y-axis).
- *
- * x*x z*z
- * ----- + ----- - 1 = 0
- * a*a c*c
- *
- */
-
- if ((A > 0.0) && (E == 0.0) && (H > 0.0) && (J < 0.0))
- {
- a = sqrt(-J/A);
- c = sqrt(-J/H);
-
- NewMin[X] = -a;
- NewMin[Z] = -c;
- NewMax[X] = a;
- NewMax[Z] = c;
- }
-
- /*
- *
- * Check for cylinder (z-axis).
- *
- * x*x y*y
- * ----- + ----- - 1 = 0
- * a*a b*b
- *
- */
-
- if ((A > 0.0) && (E > 0.0) && (H == 0.0) && (J < 0.0))
- {
- a = sqrt(-J/A);
- b = sqrt(-J/E);
-
- NewMin[X] = -a;
- NewMin[Y] = -b;
- NewMax[X] = a;
- NewMax[Y] = b;
- }
-
- /*
- *
- * Check for cone (x-axis).
- *
- * x*x y*y z*z
- * ----- - ----- - ----- = 0
- * a*a b*b c*c
- *
- */
-
- if ((A > 0.0) && (E < 0.0) && (H < 0.0) && (J == 0.0))
- {
- a = sqrt(1.0/A);
- b = sqrt(-1.0/E);
- c = sqrt(-1.0/H);
-
- /* Get radii for lower x value. */
-
- x = ClipMin[X];
-
- ry1 = fabs(x * b / a);
- rz1 = fabs(x * c / a);
-
- /* Get radii for upper x value. */
-
- x = ClipMax[X];
-
- ry2 = fabs(x * b / a);
- rz2 = fabs(x * c / a);
-
- ry = max(ry1, ry2);
- rz = max(rz1, rz2);
-
- NewMin[Y] = -ry;
- NewMin[Z] = -rz;
- NewMax[Y] = ry;
- NewMax[Z] = rz;
- }
-
- /*
- *
- * Check for cone (y-axis).
- *
- * x*x y*y z*z
- * ----- - ----- + ----- = 0
- * a*a b*b c*c
- *
- */
-
- if ((A > 0.0) && (E < 0.0) && (H > 0.0) && (J == 0.0))
- {
- a = sqrt(1.0/A);
- b = sqrt(-1.0/E);
- c = sqrt(1.0/H);
-
- /* Get radii for lower y value. */
-
- y = ClipMin[Y];
-
- rx1 = fabs(y * a / b);
- rz1 = fabs(y * c / b);
-
- /* Get radii for upper y value. */
-
- y = ClipMax[Y];
-
- rx2 = fabs(y * a / b);
- rz2 = fabs(y * c / b);
-
- rx = max(rx1, rx2);
- rz = max(rz1, rz2);
-
- NewMin[X] = -rx;
- NewMin[Z] = -rz;
- NewMax[X] = rx;
- NewMax[Z] = rz;
- }
-
- /*
- *
- * Check for cone (z-axis).
- *
- * x*x y*y z*z
- * ----- + ----- - ----- = 0
- * a*a b*b c*c
- *
- */
-
- if ((A > 0.0) && (E > 0.0) && (H < 0.0) && (J == 0.0))
- {
- a = sqrt(1.0/A);
- b = sqrt(1.0/E);
- c = sqrt(-1.0/H);
-
- /* Get radii for lower z value. */
-
- z = ClipMin[Z];
-
- rx1 = fabs(z * a / c);
- ry1 = fabs(z * b / c);
-
- /* Get radii for upper z value. */
-
- z = ClipMax[Z];
-
- rx2 = fabs(z * a / c);
- ry2 = fabs(z * b / c);
-
- rx = max(rx1, rx2);
- ry = max(ry1, ry2);
-
- NewMin[X] = -rx;
- NewMin[Y] = -ry;
- NewMax[X] = rx;
- NewMax[Y] = ry;
- }
-
- /*
- *
- * Check for hyperboloid (x-axis).
- *
- * x*x y*y z*z
- * ----- - ----- - ----- + 1 = 0
- * a*a b*b c*c
- *
- */
-
- if ((A > 0.0) && (E < 0.0) && (H < 0.0) && (J > 0.0))
- {
- /* Get radii for lower x value. */
-
- x = ClipMin[X];
-
- d = 1.0 + A * Sqr(x);
-
- ry1 = sqrt(-d / E);
- rz1 = sqrt(-d / H);
-
- /* Get radii for upper x value. */
-
- x = ClipMax[X];
-
- d = 1.0 + A * Sqr(x);
-
- ry2 = sqrt(-d / E);
- rz2 = sqrt(-d / H);
-
- ry = max(ry1, ry2);
- rz = max(rz1, rz2);
-
- NewMin[Y] = -ry;
- NewMin[Z] = -rz;
- NewMax[Y] = ry;
- NewMax[Z] = rz;
- }
-
- /*
- *
- * Check for hyperboloid (y-axis).
- *
- * x*x y*y z*z
- * ----- - ----- + ----- - 1 = 0
- * a*a b*b c*c
- *
- */
-
- if ((A > 0.0) && (E < 0.0) && (H > 0.0) && (J < 0.0))
- {
- /* Get radii for lower y value. */
-
- y = ClipMin[Y];
-
- d = 1.0 - E * Sqr(y);
-
- rx1 = sqrt(d / A);
- rz1 = sqrt(d / H);
-
- /* Get radii for upper y value. */
-
- y = ClipMax[Y];
-
- d = 1.0 - E * Sqr(y);
-
- rx2 = sqrt(d / A);
- rz2 = sqrt(d / H);
-
- rx = max(rx1, rx2);
- rz = max(rz1, rz2);
-
- NewMin[X] = -rx;
- NewMin[Z] = -rz;
- NewMax[X] = rx;
- NewMax[Z] = rz;
- }
-
- /*
- *
- * Check for hyperboloid (z-axis).
- *
- * x*x y*y z*z
- * ----- + ----- - ----- - 1 = 0
- * a*a b*b c*c
- *
- */
-
- if ((A > 0.0) && (E > 0.0) && (H < 0.0) && (J < 0.0))
- {
- /* Get radii for lower z value. */
-
- z = ClipMin[Z];
-
- d = 1.0 - H * Sqr(z);
-
- rx1 = sqrt(d / A);
- ry1 = sqrt(d / E);
-
- /* Get radii for upper z value. */
-
- z = ClipMax[Z];
-
- d = 1.0 - H * Sqr(z);
-
- rx2 = sqrt(d / A);
- ry2 = sqrt(d / E);
-
- rx = max(rx1, rx2);
- ry = max(ry1, ry2);
-
- NewMin[X] = -rx;
- NewMin[Y] = -ry;
- NewMax[X] = rx;
- NewMax[Y] = ry;
- }
-
- /*
- *
- * Check for paraboloid (x-axis).
- *
- * y*y z*z
- * x - ----- - ----- = 0
- * b*b c*c
- *
- */
-
- if ((A == 0.0) && (D != 0.0) && (E != 0.0) && (H != 0.0) && (J == 0.0))
- {
- /* Get radii for lower x value. */
-
- x = ClipMin[X];
-
- ry1 = sqrt(fabs(2.0 * D * x / E));
- rz1 = sqrt(fabs(2.0 * D * x / H));
-
- /* Get radii for upper x value. */
-
- x = ClipMax[X];
-
- ry2 = sqrt(fabs(2.0 * D * x / E));
- rz2 = sqrt(fabs(2.0 * D * x / H));
-
- ry = max(ry1, ry2);
- rz = max(rz1, rz2);
-
- NewMin[Y] = -ry;
- NewMin[Z] = -rz;
- NewMax[Y] = ry;
- NewMax[Z] = rz;
- }
-
- /*
- *
- * Check for paraboloid (y-axis).
- *
- * x*x z*z
- * y - ----- - ----- = 0
- * a*a c*c
- *
- */
-
- if ((E == 0.0) && (G != 0.0) && (A != 0.0) && (H != 0.0) && (J == 0.0))
- {
- /* Get radii for lower y-value. */
-
- y = ClipMin[Y];
-
- rx1 = sqrt(fabs(2.0 * G * y / A));
- rz1 = sqrt(fabs(2.0 * G * y / H));
-
- /* Get radii for upper y value. */
-
- y = ClipMax[Y];
-
- rx2 = sqrt(fabs(2.0 * G * y / A));
- rz2 = sqrt(fabs(2.0 * G * y / H));
-
- rx = max(rx1, rx2);
- rz = max(rz1, rz2);
-
- NewMin[X] = -rx;
- NewMin[Z] = -rz;
- NewMax[X] = rx;
- NewMax[Z] = rz;
- }
-
- /*
- *
- * Check for paraboloid (z-axis).
- *
- * x*x y*y
- * z - ----- - ----- = 0
- * a*a b*b
- *
- */
-
- if ((H == 0.0) && (I != 0.0) && (A != 0.0) && (E != 0.0) && (J == 0.0))
- {
- /* Get radii for lower z-value. */
-
- z = ClipMin[Z];
-
- rx1 = sqrt(fabs(2.0 * I * z / A));
- ry1 = sqrt(fabs(2.0 * I * z / E));
-
- /* Get radii for upper z value. */
-
- z = ClipMax[Z];
-
- rx2 = sqrt(fabs(2.0 * I * z / A));
- ry2 = sqrt(fabs(2.0 * I * z / E));
-
- rx = max(rx1, rx2);
- ry = max(ry1, ry2);
-
- NewMin[X] = -rx;
- NewMin[Y] = -ry;
- NewMax[X] = rx;
- NewMax[Y] = ry;
- }
-
- /* Intersect clipping object's and quadric's bounding boxes */
-
- NewMin[X] = max(NewMin[X], ClipMin[X]);
- NewMin[Y] = max(NewMin[Y], ClipMin[Y]);
- NewMin[Z] = max(NewMin[Z], ClipMin[Z]);
-
- NewMax[X] = min(NewMax[X], ClipMax[X]);
- NewMax[Y] = min(NewMax[Y], ClipMax[Y]);
- NewMax[Z] = min(NewMax[Z], ClipMax[Z]);
-
- /* Use old or new bounding box? */
-
- New_Volume = (NewMax[X] - NewMin[X]) * (NewMax[Y] - NewMin[Y]) * (NewMax[Z] - NewMin[Z]);
-
- BOUNDS_VOLUME(Old_Volume, Old);
-
- if (New_Volume < Old_Volume)
- {
- /* Add translation. */
-
- VAddEq(NewMin, T1);
- VAddEq(NewMax, T1);
-
- Make_BBox_from_min_max(Quadric->BBox, NewMin, NewMax);
-
- /* Beware of bounding boxes to large. */
-
- if ((Quadric->BBox.Lengths[X] > CRITICAL_LENGTH) ||
- (Quadric->BBox.Lengths[Y] > CRITICAL_LENGTH) ||
- (Quadric->BBox.Lengths[Z] > CRITICAL_LENGTH))
- {
- Make_BBox(Quadric->BBox, -BOUND_HUGE/2, -BOUND_HUGE/2, -BOUND_HUGE/2,
- BOUND_HUGE, BOUND_HUGE, BOUND_HUGE);
- }
- }
- }
-
-
-
- /*****************************************************************************
- *
- * FUNCTION
- *
- * Compute_Plane_Min_Max
- *
- * INPUT
- *
- * Plane - Plane
- * Min, Max - Vectors containing plane's dimensions
- *
- * OUTPUT
- *
- * Min, Max
- *
- * RETURNS
- *
- * AUTHOR
- *
- * Dieter Bayer
- *
- * DESCRIPTION
- *
- * Compute min/max vectors for planes perpendicular to an axis.
- *
- * CHANGES
- *
- * May 1994 : Creation.
- *
- ******************************************************************************/
-
- void Compute_Plane_Min_Max(Plane, Min, Max)
- PLANE *Plane;
- VECTOR Min, Max;
- {
- DBL d;
- VECTOR N;
-
- Assign_Vector(N, Plane->Normal_Vector);
-
- d = -Plane->Distance;
-
- Min[X] = Min[Y] = Min[Z] = -BOUND_HUGE/2;
- Max[X] = Max[Y] = Max[Z] = BOUND_HUGE/2;
-
- /* y-z-plane */
-
- if (fabs(1.0 - fabs(N[X])) < EPSILON)
- {
- if (N[X] > 0.0)
- {
- Max[X] = d;
- }
- else
- {
- Min[X] = -d;
- }
- }
-
- /* x-z-plane */
-
- if (fabs(1.0 - fabs(N[Y])) < EPSILON)
- {
- if (N[Y] > 0.0)
- {
- Max[Y] = d;
- }
- else
- {
- Min[Y] = -d;
- }
- }
-
- /* x-y-plane */
-
- if (fabs(1.0 - fabs(N[Z])) < EPSILON)
- {
- if (N[Z] > 0.0)
- {
- Max[Z] = d;
- }
- else
- {
- Min[Z] = -d;
- }
- }
- }
-
-
-
-